<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>WeakMap</title>
</head>
<body>
<script>
    /**
     * WeakMap：生成键值对的集合【类似Map】
     * 两点区别：1. WeakMap只接受【对象】作为键名（null除外），不接受其他类型的值作为键名
     *          2. 和WeakSet一样，不计入垃圾回收机制
     *
     * */
    // WeakMap 可以使用 set 方法添加成员
    const wm1 = new WeakMap();
    const key = {foo: 1};
    wm1.set(key, 2);
    wm1.get(key) // 2

    // WeakMap 也可以接受一个数组，
    // 作为构造函数的参数
    const k1 = [1, 2, 3];
    const k2 = [4, 5, 6];
    const wm2 = new WeakMap([[k1, 'foo'], [k2, 'bar']]);
    wm2.get(k2) // "bar"


    // 接受参数不同：只收对象
    const map = new WeakMap();
    map.set(1, 2)// TypeError: 1 is not an object!
    map.set(Symbol(), 2)// TypeError: Invalid value used as weak map key
    map.set(null, 2)// TypeError: Invalid value used as weak map key


    /// 设计目标解释：在某个对象上面存放一些数据，但是这会形成对于这个对象的引用
    const e1 = document.getElementById('foo');
    const e2 = document.getElementById('bar');
    const arr = [
      [e1, 'foo 元素'],
      [e2, 'bar 元素'], // ==> 分别在对象 e1 e2 上添加一些说明，这就引用了对象
    ];
    /* 一旦不再需要这两个对象，我们就必须手动删除这个引用，否则垃圾回收机制就不会释放e1和e2占用的内存
    *    // 不需要 e1 和 e2 的时候
         // 必须手动删除引用
         arr [0] = null;
         arr [1] = null;
    * */
    // 注意：就是说它会自动为你清除【WeakMap结构有助于防止内存泄漏】

    // 应用：在网页的 DOM 元素上添加数据。当该 DOM 元素被清除，其所对应的WeakMap记录就会【自动被移除】
    const wm = new WeakMap();

    const element = document.getElementById('example');

    wm.set(element, 'some information');
    wm.get(element) // "some information"

    /* 注意：WeakMap 弱引用的只是【键名】，而【不是键值】。键值依然是正常引用 */
    const wm = new WeakMap();
    let key = {};
    let obj = {foo: 1};

    wm.set(key, obj);
    obj = null;
    wm.get(key)
    // Object {foo: 1}

    /*
    * 注意点：1、 没有遍历操作（即没有keys()、values()和entries()方法），也没有size属性【与垃圾回收机制有关】
    *        2、无法清空，即不支持clear方法
    *
    * 只支持四个方法：get()、set()、has()、delete()
    *
    * */
</script>
</body>
</html>